package com.itany.lambda;


import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;

/**
 * @Author:石小俊
 * @Date:2022/11/17 9:43
 * @Version:1.0-SNAPSHOT
 * @Description:
 */
public class Test02 {

    public static void main(String[] args) {
        // 匿名内部类用法
        testConsumer(new Consumer<String>() {
            @Override
            public void accept(String s) {
                System.out.println(s);
            }
        },"admin");

        // Lambda表达式
        testConsumer(
            (s) -> System.out.println("学习Lambda表达式太类了,我想"+s),"睡一觉");

        System.out.println("------------------------------------");

        // 匿名内部类用法
        List<String> result = testSupplier(new Supplier<List<String>>() {
            @Override
            public List<String> get() {
                return Arrays.asList("孙尚香","蔡文姬","貂蝉","吕布","赵云");
            }
        });
        System.out.println(result);

        // Lambda表达式用法
        List<String> result2 = testSupplier(() -> Arrays.asList("孙尚香","蔡文姬","貂蝉","吕布","赵云"));
        System.out.println(result2);

        System.out.println("------------------------------------");


        List<String> addressList = Arrays.asList("南京","北京","上海","苏州","常州","泰州");
        // 匿名内部类用法
        testPredicate(new Predicate<String>() {
            @Override
            public boolean test(String s) {
                return s.contains("京");
            }
        },addressList);

        // Lambda表达式用法
        testPredicate(s -> s.contains("州"),addressList);

        System.out.println("------------------------------------");
        List<Integer> ids = Arrays.asList(1,3,5,6,8);
        // 匿名内部类用法
        Integer length = testFunction(new Function<List<Integer>, Integer>() {
            @Override
            public Integer apply(List<Integer> ids) {
                return ids.size();
            }
        }, ids);
        System.out.println(length);

        // Lambda表达式用法
        Integer length2 = testFunction(f -> f.size(), ids);
        System.out.println(length2);

    }

    /**
     * 消费型接口Consumer<T>,接口方法:void accept(T t)
     * 当前接口的泛型类型与实际调用accept方法时传递的参数类型一致
     * 由于此处并不是真正的实际调用者,该方法会被其他方法所调用
     * 因此,accept方法中的参数可以设置为形参
     * 此时,泛型的类型与传递的形参类型一致
     * @param consumer  消费型接口
     * @param  param    消费型接口所需要的形参
     */
    public static void testConsumer(Consumer<String> consumer,String param){
        consumer.accept(param);
    }

    /**
     * 供给型接口Supplier<T>,方法:T get()
     * 该接口有返回值,无参
     * @param supplier
     * @return  返回值来自于方法的调用者
     *          调用者可以使用Lambda表达式对供给型接口进行实现
     */
    public static List<String> testSupplier(Supplier<List<String>> supplier){
        List<String> result = supplier.get();
        return result;
    }

    /**
     * 断言型接口Predicate<T>,方法:boolean test(T t)
     * 该接口一般会与另一个参数联合使用,方法需要参数
     * 泛型的类型与test方法传递的参数类型一致
     * 该接口返回值类型为布尔类型,用于判断给定的参数是否符合指定的规则
     * 该规则由调用者调用该接口时进行实现
     * @param predicate
     * @param list
     */
    public static void testPredicate(Predicate<String> predicate, List<String> list){
        for(String s : list){
            if(predicate.test(s)){
                System.out.println(s);
            }
        }
    }


    /**
     * 函数型接口Function<T,R>,方法:R apply(T t)
     * 该接口第一个泛型表示接口方法调用的参数的类型
     * 该接口的第二个泛型表示接口方法返回值类型
     * @param function
     * @param list
     * @return
     */
    public static Integer testFunction(Function<List<Integer>,Integer> function, List<Integer> list){
        return function.apply(list);
    }
}
